﻿using System;
using System.Data.Objects.DataClasses;
using AutoMapper;
using FluentAssertions;
using Xunit;
using myCollections.BL.Services;
using myCollections.Data.SqlLite;

namespace myCollectionsTests.BL.Services
{
    public class ExportMapperTests
    {
        private readonly ExportMapper mapper;

        private readonly string id = Guid.NewGuid().ToString();
        private readonly byte[] Cover = new byte[] { 2, 2, 2 };
        private readonly Media media = new Media { Name = "Media name" };
        private const string filePath = "file path";
        private const string fileName = "File name";
        private const string description = "DESCRIPTION";
        private const string title = "Title";
        private DateTime releaseDate = DateTime.Now;
        private DateTime addedDate = DateTime.Now;
        private const long rating = 2;
        private const string displayName = "Display Name";
        private const string studio = "Studio";
        private const string artistJob = "Artist Job";

        public ExportMapperTests()
        {
            mapper = new ExportMapper();
            mapper.MusicMapper();
            mapper.BooksMapper();
            mapper.AppsMapper();
            mapper.GamesMapper();
            mapper.MovieMapper();
            mapper.NdsMapper();
            mapper.SeriesMapper();
            mapper.XXXMapper();
        }

        #region Music

        [Fact]
        public void should_be_mapping_Music()
        {
            var music = GetMusic();

            var entity = Mapper.Map<Music, ExportObject>(music);

            entity.Id.Should().Be(id);
            entity.SmallCover.Should().BeEquivalentTo(Cover);
            entity.Title.Should().Be(title);
            entity.Artist.Should().Be(string.Format("{0}, {1}", artistJob, artistJob));
            entity.Studio.Should().Be(studio);
            entity.ReleaseDate.Should().Be(releaseDate.ToString("ddMMyyyy"));
            entity.Rating.Should().Be(2);
            entity.Description.Should().Be(description);
            entity.Type.Should().Be(string.Format("{0}, {1}, {2}", displayName, displayName, displayName));
            entity.AddedDate.Should().Be(addedDate.ToString("ddMMyyyy"));
            entity.MediaName.Should().Be(media.Name);
            entity.FileName.Should().Be(fileName);
            entity.FilePath.Should().Be(filePath);
        }

        [Fact(Skip = "")]
        public void should_not_thow_exeption_if_Music_Artist_Job_is_not_set()
        {
            var music = GetMusic();

            music.Music_Artist_Job = new EntityCollection<Music_Artist_Job>();

           Action act = () =>  Mapper.Map<Music, ExportObject>(music);
           
            act.ShouldNotThrow();
        }

        [Fact]
        public void should_not_thow_exeption_if_Music_Studio_for_Music_is_not_set()
        {
            var music = GetMusic();
            music.Music_Studio = null;

            Action act = () => Mapper.Map<Music, ExportObject>(music);

            act.ShouldNotThrow();
        }

        [Fact]
        public void should_not_thow_exeption_if_ReleaseDate_for_Music_is_not_set()
        {
            var music = GetMusic();
            music.ReleaseDate = null;

            Action act = () => Mapper.Map<Music, ExportObject>(music);

            act.ShouldNotThrow();
        }

        [Fact(Skip = "")]
        public void should_not_throw_exeption_if_Music_MusicGenre_for_Misic_is_not_set()
        {
            var music = GetMusic();
            music.Music_MusicGenre = null;

            Action act = () => Mapper.Map<Music, ExportObject>(music);

            act.ShouldNotThrow();

        }

        #endregion

        #region Books

        [Fact]
        public void should_be_mapping_Book()
        {
            var book = GetBooks();

            var entity = Mapper.Map<Books, ExportObject>(book);

            entity.Id.Should().Be(id);
            entity.SmallCover.Should().BeEquivalentTo(Cover);
            entity.Title.Should().Be(title);
            entity.Artist.Should().Be(string.Format("{0}, {1}", artistJob, artistJob));
            entity.Studio.Should().Be(studio);
            entity.ReleaseDate.Should().Be(releaseDate.ToString("ddMMyyyy"));
            entity.Rating.Should().Be(rating);
            entity.Description.Should().Be(description);
            entity.Type.Should().Be(string.Format("{0}, {1}, {2}", displayName, displayName, displayName));
            entity.AddedDate.Should().Be(addedDate.ToString("ddMMyyyy"));
            entity.MediaName.Should().Be(media.Name);
            entity.FileName.Should().Be(fileName);
            entity.FilePath.Should().Be(filePath);
        }

        [Fact]
        public void should_not_thow_exeption_if_App_Editor_for_Books_is_not_set()
        {
            var book = GetBooks();
            book.App_Editor = null;

            Action act = () => Mapper.Map<Books, ExportObject>(book);

            act.ShouldNotThrow();
        }

        [Fact]
        public void should_not_thow_exeption_if_ReleaseDate_for_Books_is_not_set()
        {
            var book = GetBooks();
            book.ReleaseDate = null;

            Action act = () => Mapper.Map<Books, ExportObject>(book);

            act.ShouldNotThrow();
        }

        #endregion

        #region Apps

        [Fact]
        public void should_be_mapping_Apps()
        {
            var app = GetApps();

            var entity = Mapper.Map<Apps, ExportObject>(app);

            entity.Id.Should().Be(id);
            entity.SmallCover.Should().BeEquivalentTo(Cover);
            entity.Title.Should().Be(title);
            //entity.Artist.Should().Be(string.Format("{0}, {1}", artistJob, artistJob));
            entity.Studio.Should().Be(studio);
            entity.ReleaseDate.Should().Be(releaseDate.ToString("ddMMyyyy"));
            entity.Rating.Should().Be(2);
            entity.Description.Should().Be(description);
            entity.Type.Should().Be(string.Format("{0}, {1}, {2}", displayName, displayName, displayName));
            entity.AddedDate.Should().Be(addedDate.ToString("ddMMyyyy"));
            entity.MediaName.Should().Be(media.Name);
            entity.FileName.Should().Be(fileName);
            entity.FilePath.Should().Be(filePath);
        }

        [Fact]
        public void should_not_thow_exeption_if_App_Editor_for_Apps_is_not_set()
        {
            var app = GetApps();
            app.App_Editor = null;

            Action act = () => Mapper.Map<Apps, ExportObject>(app);

            act.ShouldNotThrow();
        }

        [Fact]
        public void should_not_thow_exeption_if_ReleaseDate_for_Apps_is_not_set()
        {
            var app = GetApps();
            app.ReleaseDate = null;

            Action act = () => Mapper.Map<Apps, ExportObject>(app);

            act.ShouldNotThrow();
        }

        #endregion 

        #region Games

        [Fact]
        public void should_be_mapping_Games()
        {
            var game = GetGamez();

            var entity = Mapper.Map<Gamez, ExportObject>(game);

            entity.Id.Should().Be(id);
            entity.SmallCover.Should().BeEquivalentTo(Cover);
            entity.Title.Should().Be(title);
            //entity.Artist.Should().Be(string.Format("{0}, {1}", artistJob, artistJob));
            entity.Studio.Should().Be(studio);
            entity.ReleaseDate.Should().Be(releaseDate.ToString("ddMMyyyy"));
            entity.Rating.Should().Be(2);
            entity.Description.Should().Be(description);
            entity.Type.Should().Be(string.Format("{0}, {1}, {2}", displayName, displayName, displayName));
            entity.AddedDate.Should().Be(addedDate.ToString("ddMMyyyy"));
            entity.MediaName.Should().Be(media.Name);
            entity.FileName.Should().Be(fileName);
            entity.FilePath.Should().Be(filePath);
        }


        [Fact]
        public void should_not_thow_exeption_if_App_Editor_for_Gamez_is_not_set()
        {
            var game = GetGamez();
            game.App_Editor = null;

            Action act = () => Mapper.Map<Gamez, ExportObject>(game);

            act.ShouldNotThrow();
        }

        [Fact]
        public void should_not_thow_exeption_if_ReleaseDate_for_Gamez_is_not_set()
        {
            var game = GetGamez();
            game.ReleaseDate = null;

            Action act = () => Mapper.Map<Gamez, ExportObject>(game);

            act.ShouldNotThrow();
        }

        #endregion

        #region Movies

        [Fact]
        public void should_be_mapping_Movies()
        {
            var movie = GetMovie();

            var entity = Mapper.Map<Movie, ExportObject>(movie);

            entity.Id.Should().Be(id);
            entity.SmallCover.Should().BeEquivalentTo(Cover);
            entity.Title.Should().Be(title);
            entity.Artist.Should().Be(string.Format("{0}, {1}", artistJob, artistJob));
            entity.Studio.Should().Be(studio);
            entity.ReleaseDate.Should().Be(releaseDate.ToString("ddMMyyyy"));
            entity.Rating.Should().Be(2);
            entity.Description.Should().Be(description);
            entity.Type.Should().Be(string.Format("{0}, {1}, {2}", displayName, displayName, displayName));
            entity.AddedDate.Should().Be(addedDate.ToString("ddMMyyyy"));
            entity.MediaName.Should().Be(media.Name);
            entity.FileName.Should().Be(fileName);
            entity.FilePath.Should().Be(filePath);
        }

        [Fact]
        public void should_not_thow_exeption_if_Movie_Studio_for_Movie_is_not_set()
        {
            var movie = GetMovie();
            movie.Movie_Studio = null;

            Action act = () => Mapper.Map<Movie, ExportObject>(movie);

            act.ShouldNotThrow();
        }

        [Fact]
        public void should_not_thow_exeption_if_ReleaseDate_for_Movie_is_not_set()
        {
            var movie = GetMovie();
            movie.ReleaseDate = null;

            Action act = () => Mapper.Map<Movie, ExportObject>(movie);

            act.ShouldNotThrow();
        }

        #endregion

        #region Nds

        [Fact]
        public void should_be_mapping_Nds()
        {
            var nds = GetNds();

            var entity = Mapper.Map<Nds, ExportObject>(nds);

            entity.Id.Should().Be(id);
            entity.SmallCover.Should().BeEquivalentTo(Cover);
            entity.Title.Should().Be(title);
            entity.Studio.Should().Be(studio);
            entity.ReleaseDate.Should().Be(releaseDate.ToString("ddMMyyyy"));
            entity.Rating.Should().Be(2);
            entity.Description.Should().Be(description);
            entity.Type.Should().Be(string.Format("{0}, {1}, {2}", displayName, displayName, displayName));
            entity.AddedDate.Should().Be(addedDate.ToString("ddMMyyyy"));
            entity.MediaName.Should().Be(media.Name);
            entity.FileName.Should().Be(fileName);
            entity.FilePath.Should().Be(filePath);
        }

        [Fact]
        public void should_not_thow_exeption_if_App_Editor_for_Nds_is_not_set()
        {
            var nds = GetNds();
            nds.App_Editor = null;

            Action act = () => Mapper.Map<Nds, ExportObject>(nds);

            act.ShouldNotThrow();
        }

        [Fact]
        public void should_not_thow_exeption_if_ReleaseDate_for_Nds_is_not_set()
        {
            var nds = GetNds();
            nds.ReleaseDate = null;

            Action act = () => Mapper.Map<Nds, ExportObject>(nds);

            act.ShouldNotThrow();
        }

        #endregion

        #region Series

        [Fact]
        public void should_be_mapping_Series_Season()
        {
            var series = GetSeriesSeason();

            var entity = Mapper.Map<SeriesSeason, ExportObject>(series);

            entity.Id.Should().Be(id);
            entity.SmallCover.Should().BeEquivalentTo(Cover);
            entity.Title.Should().Be(title);
            entity.Artist.Should().Be(string.Format("{0}, {1}", artistJob, artistJob));
            entity.Studio.Should().Be(studio);
            entity.ReleaseDate.Should().Be(releaseDate.ToString("ddMMyyyy"));
            entity.Rating.Should().Be(2);
            //entity.Description.Should().Be(description);
            entity.Type.Should().Be(string.Format("{0}, {1}, {2}", displayName, displayName, displayName));
            entity.AddedDate.Should().Be(addedDate.ToString("ddMMyyyy"));
            entity.MediaName.Should().Be(media.Name);
            //entity.FileName.Should().Be(fileName);
            entity.FilePath.Should().Be(filePath);
        }

        [Fact]
        public void should_not_thow_exeption_if_Movie_Studio_for_Series_is_not_set()
        {
           // Series.Movie_Studio.Name

            var series = GetSeriesSeason();
            series.Series.Movie_Studio = null;

            Action act = () => Mapper.Map<SeriesSeason, ExportObject>(series);

            act.ShouldNotThrow();
        }

        [Fact]
        public void should_not_thow_exeption_if_ReleaseDate_for_Series_is_not_set()
        {
            var series = GetSeriesSeason();
            series.ReleaseDate = null;

            Action act = () => Mapper.Map<SeriesSeason, ExportObject>(series);

            act.ShouldNotThrow();
        }

        #endregion

        #region XXX

        [Fact]
        public void should_be_mapping_XXX()
        {
            var xxx = GetXxx();

            var entity = Mapper.Map<XXX, ExportObject>(xxx);

            entity.Id.Should().Be(id);
            entity.SmallCover.Should().BeEquivalentTo(Cover);
            entity.Title.Should().Be(title);
            entity.Studio.Should().Be(studio);
            entity.ReleaseDate.Should().Be(releaseDate.ToString("ddMMyyyy"));
            entity.Rating.Should().Be(2);
            entity.Description.Should().Be(description);
            entity.Type.Should().Be(string.Format("{0}, {1}, {2}", displayName, displayName, displayName));
            entity.AddedDate.Should().Be(addedDate.ToString("ddMMyyyy"));
            entity.MediaName.Should().Be(media.Name);
            entity.FileName.Should().Be(fileName);
            entity.FilePath.Should().Be(filePath);
        }

        [Fact]
        public void should_not_thow_exeption_if_XXX_Studio_for_XXX_is_not_set()
        {
            // Series.Movie_Studio.Name

            var xxx = GetXxx();
            xxx.XXX_Studio = null;

            Action act = () => Mapper.Map<XXX, ExportObject>(xxx);

            act.ShouldNotThrow();
        }

        [Fact]
        public void should_not_thow_exeption_if_ReleaseDate_for_XXX_is_not_set()
        {
            var xxx = GetXxx();
            xxx.ReleaseDate = null;

            Action act = () => Mapper.Map<XXX, ExportObject>(xxx);

            act.ShouldNotThrow();
        }

        #endregion

        private Books GetBooks()
        {
            var book = new Books()
            {
                Id = id,
                Cover = Cover,
                Title = title,
                Book_Artist_Job = new EntityCollection<Book_Artist_Job>
                        {
                            new Book_Artist_Job {Artist = new Artist {FulleName = artistJob}},
                            new Book_Artist_Job {Artist = new Artist {FulleName = artistJob}}
                        },
                App_Editor = new App_Editor { Name = studio },
                ReleaseDate = releaseDate,
                Rating = rating,
                Description = description,
                Books_BookType = new EntityCollection<Books_BookType>
                        {
                            new Books_BookType {BookType = new BookType {DisplayName = displayName}},
                            new Books_BookType {BookType = new BookType {DisplayName = displayName}},
                            new Books_BookType {BookType = new BookType {DisplayName = displayName}}
                        },
                AddedDate = addedDate,
                Media = media,
                FilePath = filePath,
                FileName = fileName
            };
            return book;
        }
      
        private Music GetMusic()
        {
            var music = new Music()
            {
                Id = id,
                Cover = Cover,
                Title = title,
                Music_Artist_Job = new EntityCollection<Music_Artist_Job>
                        {
                            new Music_Artist_Job {Artist = new Artist() {FulleName = artistJob}},
                            new Music_Artist_Job {Artist = new Artist() {FulleName = artistJob}}
                        },
                Music_Studio = new Music_Studio { Name = studio },
                ReleaseDate = releaseDate,
                Rating = 2,
                Description = description,
                Music_MusicGenre = new EntityCollection<Music_MusicGenre>
                        {
                            new Music_MusicGenre {Music_Genre = new Music_Genre {DisplayName = displayName}},
                            new Music_MusicGenre {Music_Genre = new Music_Genre {DisplayName = displayName}},
                            new Music_MusicGenre {Music_Genre = new Music_Genre {DisplayName = displayName}}
                        },
                AddedDate = addedDate,
                Media = media,
                FileName = fileName,
                FilePath = filePath
            };
            return music;
        }

        private Apps GetApps()
        {
            var app = new Apps()
            {
                Id = id,
                Cover = Cover,
                Title = title,
                Version = "", //
                App_Editor = new App_Editor() { Name = studio },
                ReleaseDate = releaseDate,
                Rating = 2,
                Description = description,
                Apps_AppType = new EntityCollection<Apps_AppType>
                        {
                            new Apps_AppType {AppType = new AppType {DisplayName = displayName}},
                            new Apps_AppType {AppType = new AppType {DisplayName = displayName}},
                            new Apps_AppType {AppType = new AppType {DisplayName = displayName}}
                        },
                AddedDate = addedDate,
                Media = media,
                FileName = fileName,
                FilePath = filePath
            };
            return app;
        }

        private Gamez GetGamez()
        {
            var game = new Gamez
            {
                Id = id,
                Cover = Cover,
                Title = title,
                // Platform = new Platform{Name = },//
                App_Editor = new App_Editor() { Name = studio },
                ReleaseDate = releaseDate,
                Rating = 2,
                Description = description,
                Gamez_GamezType = new EntityCollection<Gamez_GamezType>
                        {
                            new Gamez_GamezType {GamezType = new GamezType {DisplayName = displayName}},
                            new Gamez_GamezType {GamezType = new GamezType {DisplayName = displayName}},
                            new Gamez_GamezType {GamezType = new GamezType {DisplayName = displayName}}
                        },
                AddedDate = addedDate,
                Media = media,
                FileName = fileName,
                FilePath = filePath
            };
            return game;
        }

        private Movie GetMovie()
        {
            var movie = new Movie
            {
                Id = id,
                Cover = Cover,
                Title = title,
                OriginalTitle = "", //
                Movie_Studio = new Movie_Studio() { Name = studio },
                ReleaseDate = releaseDate,
                Rating = 2,
                Description = description,
                Movie_MovieGenre = new EntityCollection<Movie_MovieGenre>
                        {
                            new Movie_MovieGenre {Movie_Genre = new Movie_Genre {DisplayName = displayName}},
                            new Movie_MovieGenre {Movie_Genre = new Movie_Genre {DisplayName = displayName}},
                            new Movie_MovieGenre {Movie_Genre = new Movie_Genre {DisplayName = displayName}}
                        },
                Movie_Artist_Job = new EntityCollection<Movie_Artist_Job>
                        {
                            new Movie_Artist_Job {Artist = new Artist {FulleName = artistJob}},
                            new Movie_Artist_Job {Artist = new Artist {FulleName = artistJob}},
                        },
                AddedDate = addedDate,
                Media = media,
                FileName = fileName,
                FilePath = filePath
            };
            return movie;
        }

        private Nds GetNds()
        {
            var nds = new Nds
            {
                Id = id,
                Cover = Cover,
                Title = title,
                App_Editor = new App_Editor { Name = studio },
                ReleaseDate = releaseDate,
                Rating = 2,
                Description = description,
                Nds_GamezType = new EntityCollection<Nds_GamezType>
                        {
                            new Nds_GamezType {GamezType = new GamezType {DisplayName = displayName}},
                            new Nds_GamezType {GamezType = new GamezType {DisplayName = displayName}},
                            new Nds_GamezType {GamezType = new GamezType {DisplayName = displayName}}
                        },
                AddedDate = addedDate,
                Media = media,
                FileName = fileName,
                FilePath = filePath
            };
            return nds;
        }

        private SeriesSeason GetSeriesSeason()
        {
            var series = new SeriesSeason
            {
                Id = id,
                Cover = Cover,
                Series = new Series
                {
                    Title = title,
                    Movie_Studio = new Movie_Studio { Name = studio },
                    Series_MovieGenre = new EntityCollection<Series_MovieGenre>
                                {
                                    new Series_MovieGenre {Movie_Genre = new Movie_Genre {DisplayName = displayName}},
                                    new Series_MovieGenre {Movie_Genre = new Movie_Genre {DisplayName = displayName}},
                                    new Series_MovieGenre {Movie_Genre = new Movie_Genre {DisplayName = displayName}}
                                },
                    Series_Artist_Job = new EntityCollection<Series_Artist_Job>
                                {
                                    new Series_Artist_Job {Artist = new Artist {FulleName = artistJob}},
                                    new Series_Artist_Job {Artist = new Artist {FulleName = artistJob}}
                                }
                },
                ReleaseDate = releaseDate,
                Rating = 2,
                Season = 2, // not use
                AddedDate = addedDate,
                Media = media,
                FilePath = filePath,
                FileName = ""
            };
            return series;
        }

        private XXX GetXxx()
        {
            var xxx = new XXX
            {
                Id = id,
                Cover = Cover,
                Title = title,
                XXX_Studio = new XXX_Studio { Name = studio },
                Language = new Language { LongName = "" }, // not use
                ReleaseDate = releaseDate,
                Rating = 2,
                Description = description,
                XXX_XXXGenre = new EntityCollection<XXX_XXXGenre>
                        {
                            new XXX_XXXGenre {XXX_Genre = new XXX_Genre {DisplayName = displayName}},
                            new XXX_XXXGenre {XXX_Genre = new XXX_Genre {DisplayName = displayName}},
                            new XXX_XXXGenre {XXX_Genre = new XXX_Genre {DisplayName = displayName}}
                        },
                AddedDate = addedDate,
                XXX_Artist_Job = new EntityCollection<XXX_Artist_Job>
                        {
                            new XXX_Artist_Job {Artist = new Artist {FulleName = artistJob}},
                            new XXX_Artist_Job {Artist = new Artist {FulleName = artistJob}}
                        },
                Media = media,
                FilePath = filePath,
                FileName = fileName
            };
            return xxx;
        }
    }
}
